from cmath import log
import math
from pstats import Stats
import numpy as np
import pandas as pd
import scipy.optimize as optimize
import scipy.interpolate as spi
import random
import matplotlib.pyplot as plt
#from astropy.modeling import models, fitting
import scipy.stats as stats
from scipy import interpolate
#import statsmodels.api as sm
import warnings

#---------------------------------------定义故障分布函数

'''
利用三次样条插值法计算故障率
'''
# def func_cdf_cub(x, a,b,c):
#     t = (a,b,c)
#     return interpolate.splev(x,t)

'''
计算高斯分布时的故障率
'''
def func_cdf_gau(x, miu, sigma):    
    warnings.filterwarnings('error')
    try:
        Y = 1 - stats.norm.cdf((np.array(x) - miu) / sigma)
        return Y.tolist()
    except:
        return '输入参数异常'

'''
计算对数高斯分布时的故障率
'''
def func_cdf_loggau(x, miu, sigma):    
    warnings.filterwarnings('error')
    try:
        Y = 1 - stats.norm.cdf((np.log(np.array(x)) - miu) / sigma)
        return Y.tolist()
    except:
        return '输入参数异常'    

'''
计算威布尔分布时的故障率
'''
def func_weib(x, m, yita, t0):
    warnings.filterwarnings('error')
    try:
        Y = np.exp(-1 * ((np.array(x) - t0) / yita) ** m)
        return Y.tolist()
    except: 
        return '输入参数异常' 

'''
计算指数分布时的故障率
'''
def func_expon(x, b):
    warnings.filterwarnings('error')
    try:
        Y = np.exp(- np.array(x) / b)
        return Y.tolist()
    except: 
        return '输入参数异常' 


#————————————————————————————
#指数分布求剩余工作时间
def find_expon(reliability, b):
    a = -b * log(reliability)
    return a.real

#——————————————————————————————
#高斯分布求剩余工作时间
def find_gau(reliability, miu, sigma):
    #reliability = 0.5
    worktime = 0.1
    low = 0
    high = worktime
    while (func_cdf_gau(high,miu, sigma) > reliability):
        high = high *2
    middle = (high + low) / 2
    count = 0
    while (abs(func_cdf_gau(middle, miu, sigma)-reliability) > 0.01 and count < 1000):
        if (func_cdf_gau(middle, miu, sigma) < reliability):
            high = middle
        else:
            low = middle
        middle = (high + low) / 2
        count += 1
        #print(middle)
    middle = round(middle, 4)
    return middle

#————————————————————————————————
#对数高斯分布求剩余工作时间
def find_loggau(reliability, miu, sigma):
    #reliability = 0.5
    worktime = 0.1
    low = 0
    high = worktime
    while (func_cdf_loggau(high,miu, sigma) > reliability):
        high = high *2
    middle = (high + low) / 2
    count = 0
    while (abs(func_cdf_loggau(middle, miu, sigma)-reliability) > 0.01 and count < 1000):
        if (func_cdf_loggau(middle, miu, sigma) < reliability):
            high = middle
        else:
            low = middle
        middle = (high + low) / 2
        count += 1
        #print(middle)
    middle = round(middle, 4)
    return middle

#——————————————————————
#威布尔分布求剩余工作时间
def find_weib(reliability, m, yita, t0):
    a = t0 + yita * pow(-1 * log(reliability), 1 / m)
    return a.real

#——————————————————————————
#三次样条插值法求剩余工作时间
# def find_cub(reliability, a,b,c):
#     reliability = 0.5
#     worktime = 0.1
#     low = 0
#     high = worktime
#     while (func_cdf_cub(high,a,b,c) > reliability):
#         high = high *2
#     middle = (high + low) / 2
#     count = 0
#     while (abs(func_cdf_cub(middle, a,b,c)-reliability) > 0.01 and count < 1000):
#         if (func_cdf_cub(middle, a,b,c) < reliability):
#             high = middle
#         else:
#             low = middle
#         middle = (high + low) / 2
#         count += 1
#         print(middle)
#     middle = round(middle, 4)
#     return middle

# 部件级态势感知算法交付
if __name__ == "__main__":
    #run([1,2,3,4], type = 3)
    #print(func_weib(5, 3446685051.4268165, 0, 0.24999999999552736))
    #选“指数分布”，输入以下1个参数
    b1 = {{b1}}
    #选“高斯分布”，输入以下2个参数
    miu2 = {{miu2}}
    sigma2 = {{sigma2}}
    #选“对数高斯分布”，输入以下2个参数
    miu3 = {{miu3}}
    sigma3 = {{sigma3}}
    # 选“威布尔分布”，输入以下3个参数
    m = {{m}}
    yita = {{yita}}
    t0 = {{t0}}

    tp = {{tp}}                         #选“指数分布”，tp=1；选“高斯分布”，tp=2；选“对数高斯分布”，tp=3；选“威布尔分布”，tp=4；已知参数条件下，无三次样条插值法
    x = {{x}}                           #知识图谱获取
    x = np.sort(x)
    ct = {{ct}}                         #在“可靠度计算”下的“工作时间”输入
    reliability = {{reliability}}       #在“工作时间预计”下的“可靠度”输入
    #run(x, type = tp, ct = ct)
    #print(func_weib(5, 3446685051.4268165, 0, 0.24999999999552736))

    '''
    5不需要
    '''
    Num = len(x)
    R = np.zeros(Num)
    for i in range(Num):
        R[i] = 1 - (i + 0.7) / (Num + 0.4)
    R = np.array(R)
    A = np.arange(0, x[-1], 10)
    B = list()
    '''
    type = 4 威布尔分布
    '''
    if tp == 4: 
        #print(func_weib(x, m, yita, t0))
        y = list(func_weib(x, m, yita, t0))
        A = np.arange(t0, x[-1], 10)
        for t in A:
            Bi = np.exp(-1 * ((t + 0.01 - t0) / yita) ** m)
            B.append(Bi)
        if not isinstance(y, str):
            print({"code": 1, "msg": "",
                   "chart": {"x": x.tolist(), "y": y},
                   "line": {"linex": A.tolist(), "liney": B},
                   "gzl": func_weib(ct, m, yita, t0),"yjsj":find_weib(reliability, m, yita, t0)}, end = "")
        else:
            print({"code": 0, "msg": "输入参数异常"}, end = "")


    '''
    type = 3 对数高斯分布
    '''
    if tp == 3:
        #print(func_cdf_loggau(x, miu3, sigma3))
        y = list(func_cdf_loggau(x, miu3, sigma3))
        for t in A:
            Bi = 1 - stats.norm.cdf((np.log(t + 0.01) - miu3) / sigma3)
            B.append(Bi)
        if not isinstance(y, str):
            print({"code": 1, "msg": "",
                   "chart": {"x": x.tolist(), "y": y},
                   "line": {"linex": A.tolist(), "liney": B},
                   "gzl": func_cdf_loggau(ct, miu3, sigma3),"yjsj":find_loggau(reliability, miu3, sigma3)}, end = "")
        else:
            print({"code": 0, "msg": "输入参数异常"}, end = "")

    '''
    type = 2 高斯分布
    '''
    if tp == 2:
        #print(func_cdf_gau(x, miu2, sigma2))
        y = list(func_cdf_gau(x, miu2, sigma2))
        for t in A:
            Bi = 1 - stats.norm.cdf((t - miu2) / sigma2)
            B.append(Bi)
        if not isinstance(y, str):
            print({"code": 1, "msg": "",
                   "chart": {"x": x.tolist(), "y": y},
                   "line": {"linex": A.tolist(), "liney": B},
                   "gzl": func_cdf_gau(ct, miu2, sigma2),"yjsj":find_gau(reliability, miu2, sigma2)}, end = "")
        else:
            print({"code": 0, "msg": "输入参数异常"}, end = "")

    '''
    type = 1 指数分布
    '''
    if tp == 1:
        #print(func_expon(x, b1))
        y = list(func_expon(x, b1))
        for t in A:
            Bi = np.exp(-t / b1)
            B.append(Bi)
        if not isinstance(y, str):
            print({"code": 1, "msg": "",
                   "chart": {"x": x.tolist(), "y": y},
                   "line": {"linex": A.tolist(), "liney": B},
                   "gzl": func_expon(ct, b1),"yjsj":find_expon(reliability, b1)}, end = "")
        else:
            print({"code": 0, "msg": "输入参数异常"}, end = "")